﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
using ZedGraph;
using System.Diagnostics;
using System.Reflection;
using System.IO.Ports;

namespace HRZoneTrainer
{
    public partial class HRZoneTrainer : Form
    {
        public enum GraphType
        {
            HeartRate,
            HeartRatePercentage
        }

        private enum ProgramState
        {
            Initialised,
            Reset,
            Started,
            Stopped,
        }

        public HRZoneTrainer()
        {
            InitializeComponent();
            OpenFile(Config.GetConfig().LastSessionWorkout);
            ButtonState();

            antiToolStripMenuItem.Checked = Config.GetConfig().AntiAliasing;
            HRGraph.IsAntiAlias = Config.GetConfig().AntiAliasing;

            fullScreenToolStripMenuItem.Checked = Config.GetConfig().FullScreen;
            FullScreen(Config.GetConfig().FullScreen);

            autoSaveSessionToolStripMenuItem.Checked = Config.GetConfig().AutoSave;

            SetGraphTypeMenu(Config.GetConfig().GraphType);
        }

        private void SetGraphTypeMenu(GraphType graphType)
        {
            if (graphType == GraphType.HeartRate) {
                heartRatePercentageToolStripMenuItem.Checked = false;
                heartRateToolStripMenuItem.Checked = true;
            }
            else
            {
                heartRatePercentageToolStripMenuItem.Checked = true;
                heartRateToolStripMenuItem.Checked = false;
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileOpenDialog = new OpenFileDialog();

            fileOpenDialog.InitialDirectory = DocumentBaseDirectory + "Workouts";
            fileOpenDialog.Filter = "Workouts (*.xml)|*.xml|All|*.*";
            fileOpenDialog.Multiselect = false;

            if ( fileOpenDialog.ShowDialog() == DialogResult.OK )
            {

                OpenFile(fileOpenDialog.FileName);
            }
        }

        private void loadSessionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog fileOpenDialog = new OpenFileDialog();

            fileOpenDialog.InitialDirectory = DocumentBaseDirectory + "Sessions";
            fileOpenDialog.Filter = "Sessions (*.xml)|*.xml|All|*.*";
            fileOpenDialog.Multiselect = false;

            if ( fileOpenDialog.ShowDialog() == DialogResult.OK )
            {
                try
                {
                    XmlSerializer xs = new XmlSerializer(typeof(Session));
                    FileStream fs = new FileStream(fileOpenDialog.FileName, FileMode.Open, FileAccess.Read);

                    object sessionObj = xs.Deserialize(fs);

                    if ( sessionObj is Session )
                    {
                        m_previousSession = sessionObj as Session;
                    }

                    fs.Close();

                    CreateChart(HRGraph);
                }
                catch ( Exception exception )
                {
                    MessageBox.Show(exception.Message, "Error opening workout", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
        }

        private void OpenFile(string fileName)
        {
            try
            {
                XmlSerializer xs = new XmlSerializer(typeof(workout));
                FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);

                object workoutObj = xs.Deserialize(fs);

                if ( workoutObj is workout )
                {
                    m_thisSession = new Session (workoutObj as workout);
                }

                fs.Close();

                Config.GetConfig().LastSessionWorkout = fileName;
            }
            catch ( Exception exception )
            {
                MessageBox.Show(exception.Message, "Error opening workout", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                m_thisSession = new Session(new workout());
            }

            m_thisSession.Initialise();
            CreateChart(HRGraph);
        }

        public void CreateChart(ZedGraphControl zgc)
        {
            try
            {
                GraphPane myPane = zgc.GraphPane;

                myPane.CurveList.Clear();
                myPane.GraphObjList.Clear();

                if ( Config.GetConfig().GraphType == GraphType.HeartRate )
                {
                    CreateHRChart(zgc, myPane);
                }
                else
                {
                    CreateHRPercentageChart(zgc, myPane);
                }

                CreatePhases(myPane, Config.GetConfig().GraphType);

                // Manually set the x axis range
                myPane.XAxis.Scale.Min = 0;
                myPane.XAxis.Scale.Max = m_thisSession.Duration;

                // Calculate the Axis Scale Ranges
                zgc.AxisChange();

                UpdateDisplay();
            }
            catch ( Exception ex )
            {

            }
        }

        private void CreatePhases(GraphPane myPane, GraphType graphType)
        {
            int numberOfPhases = m_thisSession.NumberOfPhases;

            double[] y = new double[numberOfPhases * 2];
            double[] x = new double[numberOfPhases * 2];

            int phaseCount = 0;
            int phaseDuration = 0;

            double HR = m_zoneCalculation.HRThreshold / 100.0;
            if ( m_zoneCalculation.GetZoneCalculationMethod() == "Maximum" )
            {
                HR = m_zoneCalculation.HRMaximum / 100.0;
            }

            foreach ( workoutEventsPhase thisPhase in m_thisSession.CurrentWorkout.events )
            {
                double intensity = Int32.Parse(thisPhase.intensity);

                if (graphType == GraphType.HeartRate) {
                    intensity *= HR;
                }

                y[phaseCount] = intensity;
                x[phaseCount] = phaseDuration;

                phaseCount++;

                phaseDuration = phaseDuration + Int32.Parse(thisPhase.duration);

                y[phaseCount] = intensity;
                x[phaseCount] = phaseDuration;

                phaseCount++;
            }

            // Generate a red curve with "Curve 1" in the legend
            LineItem myCurve = myPane.AddCurve(null, x, y, Color.Red);
            myCurve.Symbol.Type = SymbolType.None;
        }

        public void CreateHRPercentageChart(ZedGraphControl zgc, GraphPane myPane)
        {
            // Set the title and axis labels
            myPane.Title.Text = m_thisSession.CurrentWorkout.name;
            myPane.XAxis.Title.Text = "Time (s)";
            myPane.YAxis.Title.Text = "% HR " + m_zoneCalculation.GetZoneCalculationMethod();

            // Manually set the y axis range
            myPane.YAxis.Scale.Min = 0;
            myPane.YAxis.Scale.Max = 110;

            AddZones(myPane, GraphType.HeartRatePercentage);
        }

        public void CreateHRChart(ZedGraphControl zgc, GraphPane myPane)
        {
            // Set the title and axis labels
            myPane.Title.Text = m_thisSession.CurrentWorkout.name;
            myPane.XAxis.Title.Text = "Time (s)";
            myPane.YAxis.Title.Text = "HR";

            // Manually set the y axis range
            myPane.YAxis.Scale.Min = 0;
            myPane.YAxis.Scale.Max = m_zoneCalculation.HRMaximum + 20;

            AddZones(myPane, GraphType.HeartRate);
        }

        private void AddZones(GraphPane myPane, GraphType graphType)
        {
            foreach ( ZonesZoneTrainingZonesTrainingZone thisZone in m_zoneCalculation.Zones.Items[m_zoneCalculation.CurrentZoneSelectionIndex].TrainingZones )
            {
                double upper, lower;

                if ( graphType == GraphType.HeartRatePercentage )
                {
                    upper = thisZone.Percentage.Upper;
                    lower = thisZone.Percentage.Upper - thisZone.Percentage.Lower;
                }
                else
                {
                    double HR = m_zoneCalculation.HRThreshold;

                    if ( m_zoneCalculation.GetZoneCalculationMethod() == "Maximum" )
                    {
                        HR = m_zoneCalculation.HRMaximum;
                    }

                    upper = ( thisZone.Percentage.Upper * HR ) / 100.0;
                    lower = ( (thisZone.Percentage.Upper - thisZone.Percentage.Lower) * HR) / 100.0;
                }

                AddZone(myPane, thisZone.Name, Color.FromName(thisZone.Color), upper, lower);
            }
        }

        private void AddZone(GraphPane myPane, string zoneText, Color color, double upperLevel, double zoneSize)
        {
            // Draw a box item to highlight a value range
            BoxObj zone1 = new BoxObj(0, upperLevel, 1, zoneSize, Color.Empty,
                    Color.FromArgb(150, color));
            zone1.Fill = new Fill(Color.FromArgb(50, color));
            // Use the BehindAxis zorder to draw the highlight beneath the grid lines
            zone1.ZOrder = ZOrder.E_BehindCurves;
            // Make sure that the boxObj does not extend outside the chart rect if the chart is zoomed
            zone1.IsClippedToChartRect = true;
            // Use a hybrid coordinate system so the X axis always covers the full x range
            // from chart fraction 0.0 to 1.0
            zone1.Location.CoordinateFrame = CoordType.XChartFractionYScale;
            myPane.GraphObjList.Add(zone1);

            // Add a text item to label the highlighted range
            TextObj text = new TextObj(zoneText, 0.86f, upperLevel - 1, CoordType.AxisXYScale,
                                    AlignH.Left, AlignV.Center);
            text.FontSpec.Size = 8.0f;
            text.FontSpec.Fill.IsVisible = false;
            text.FontSpec.Border.IsVisible = false;
            text.FontSpec.IsBold = true;
            text.FontSpec.IsItalic = false;
            text.Location.CoordinateFrame = CoordType.XChartFractionYScale;
            text.IsClippedToChartRect = true;
            myPane.GraphObjList.Add(text);
        }
        
        private void HRZoneTrainer_FormClosed(object sender, FormClosedEventArgs e)
        {
            if ( WindowState == FormWindowState.Normal )
            {
                Config.GetConfig().Bounds = Bounds;
            }

            Config.Write();
        }

        private void UpdateDisplay()
        {
            try
            {
                labelCurrentPhase.Text = m_thisSession.CurrentPhaseTitle;
                labelPhaseDescription.Text = m_thisSession.CurrentPhaseDescription;

                int phaseTimeRemaining = m_thisSession.CurrentPhaseTimeRemaining;
                labelPhaseTime.Text = phaseTimeRemaining.ToString();

                if ( phaseTimeRemaining <= 30 )
                {
                    labelPhaseTime.ForeColor = Color.Red;
                }
                else
                {
                    labelPhaseTime.ForeColor = Color.Black;
                }

                int intensity = m_thisSession.CurrentPhaseIntensity;

                labelHRTargetLower.Text = m_zoneCalculation.GetLowerZoneHR(intensity).ToString();
                labelHRTargetUpper.Text = m_zoneCalculation.GetUpperZoneHR(intensity).ToString();

                m_thisSession.AddHRValue(m_HRLatest, m_zoneCalculation.GetZoneCalculationMethod());
                labelHR.Text = m_HRLatest.ToString();

                labelHRMonitorNoData.Visible = m_HRNoData;
                labelHRMonitorAcq.Visible = m_HRReAcquiringSeries;
                labelHRMonitorBadData.Visible = m_HRBadData;

                string fileName = "HRZoneTrainer.Images.Heart(Minus).png";

                if ( m_thisSession.CurrentPhaseCollectAverageHR )
                {
                    m_thisSession.AddAveHRValue(m_HRLatest);
                    
                    fileName = "HRZoneTrainer.Images.Heart(Plus).png";
                    labelHRAve.Text = m_thisSession.AverageHR.ToString("0");
                }

                labelHRMax.Text = m_thisSession.MaximumHR.ToString("0");

                Assembly thisExe;
                thisExe = Assembly.GetExecutingAssembly();
                Stream file = thisExe.GetManifestResourceStream(fileName);
                labelAveHRLabel.Image = Image.FromStream(file);

                HRGraph.GraphPane.CurveList.Remove(m_HRCurve);
                HRGraph.GraphPane.CurveList.Remove(m_HRCurvePreviousSession);

                if ( Config.GetConfig().GraphType == GraphType.HeartRate )
                {
                    m_HRCurve = HRGraph.GraphPane.AddCurve(null, m_thisSession.TimeValues.ToArray(), m_thisSession.HRValues.ToArray(), Color.Green, SymbolType.None);

                    if ( m_previousSession != null )
                    {
                        m_HRCurvePreviousSession = HRGraph.GraphPane.AddCurve(null, m_previousSession.TimeValues.ToArray(), m_previousSession.HRValues.ToArray(), Color.Wheat, SymbolType.None);
                    }
                }
                else
                {
                    m_HRCurve = HRGraph.GraphPane.AddCurve(null, m_thisSession.TimeValues.ToArray(), m_thisSession.HRPercentageValues.ToArray(), Color.Green, SymbolType.None);

                    if ( m_previousSession != null )
                    {
                        m_HRCurvePreviousSession = HRGraph.GraphPane.AddCurve(null, m_previousSession.TimeValues.ToArray(), m_previousSession.HRPercentageValues.ToArray(), Color.Wheat, SymbolType.None);
                    }
                }

                HRGraph.GraphPane.GraphObjList.Remove(m_tracerBox);
                // Draw a box item to highlight a value range
                m_tracerBox = new BoxObj(m_thisSession.CurrentTick - 3, 220, 8, 220, Color.Red, Color.Red);
                
                // Use the BehindAxis zorder to draw the highlight beneath the grid lines
                m_tracerBox.ZOrder = ZOrder.A_InFront;
                // Make sure that the boxObj does not extend outside the chart rect if the chart is zoomed
                m_tracerBox.IsClippedToChartRect = true;
                // Use a hybrid coordinate system so the X axis always covers the full x range
                // from chart fraction 0.0 to 1.0
                m_tracerBox.Location.CoordinateFrame = CoordType.AxisXYScale;
                HRGraph.GraphPane.GraphObjList.Add(m_tracerBox);

                HRGraph.Invalidate();
            }
            catch ( Exception )
            {

            }
        }

        public string DocumentBaseDirectory {
            get
            {
                return ( Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "HR Zone Trainer" + Path.DirectorySeparatorChar);
            }
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            timerPhase.Enabled = true;
            m_programState = ProgramState.Started;
            m_thisSession.UserMaximumHR = Config.GetConfig().HRMaximum;
            m_thisSession.UserThresholdHR = Config.GetConfig().HRThreshold;
            ButtonState();
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            timerPhase.Enabled = false;
            m_programState = ProgramState.Stopped;
            ButtonState();
        }

        private void buttonReset_Click(object sender, EventArgs e)
        {
            timerPhase.Enabled = false;
            m_programState = ProgramState.Reset;
            m_thisSession.Initialise();
            ButtonState();
            UpdateDisplay();
        }

        private void timerPhase_Tick(object sender, EventArgs e)
        {
            try
            {
                if ( m_thisSession.CurrentTick < m_thisSession.Duration )
                {
                    // Talk to the HR Board
                    byte[] bytesCommand = new byte[3];

                    bytesCommand[0] = 0x47;
                    bytesCommand[1] = 0x38;
                    bytesCommand[2] = 0xD;

                    serialPort.Write(bytesCommand, 0, 3);

                    m_thisSession.CurrentTick++;
                    UpdateDisplay();
                }
                else
                {
                    timerPhase.Enabled = false;
                    m_programState = ProgramState.Stopped;
                    ButtonState();

                    if ( Config.GetConfig().AutoSave )
                    {
                        string baseFilePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "HR Zone Trainer" + Path.DirectorySeparatorChar + "Sessions" + Path.DirectorySeparatorChar;
                        WriteFile(baseFilePath + m_thisSession.GetSaveFileName());
                    }
                }
            }
            catch (Exception ex)
            {
                timerPhase.Enabled = false;
                m_programState = ProgramState.Stopped;
                ButtonState();

                MessageBox.Show(ex.Message, "Error...", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            }
        }

        private void ButtonState()
        {
            switch ( m_programState )
            {
                case ProgramState.Initialised:
                case ProgramState.Reset:
                    buttonStart.Enabled = true;
                    buttonStop.Enabled = false;
                    buttonReset.Enabled = true;
                    break;
                case ProgramState.Started:
                    buttonStart.Enabled = false;
                    buttonStop.Enabled = true;
                    buttonReset.Enabled = false;
                    break;
                case ProgramState.Stopped:
                    buttonStart.Enabled = true;
                    buttonStop.Enabled = false;
                    buttonReset.Enabled = true;
                    break;
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox aboutBox = new AboutBox();
            aboutBox.ShowDialog();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            saveFileDialog.FileName = m_thisSession.GetSaveFileName();

            saveFileDialog.InitialDirectory = DocumentBaseDirectory + "Sessions";
            saveFileDialog.Filter = "Sessions (*.xml)|*.xml|All|*.*";

            if ( saveFileDialog.ShowDialog() == DialogResult.OK )
            {
                WriteFile(saveFileDialog.FileName);
            }
        }

        private void WriteFile(string fileName)
        {
            try
            {
                XmlSerializer writer = new XmlSerializer(typeof(Session));
                StreamWriter file = new StreamWriter(fileName);

                writer.Serialize(file, m_thisSession);
                file.Close();
            }
            catch ( Exception exception )
            {
                MessageBox.Show(exception.Message);
            }
        }

        private void clearPreviousSessionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            m_previousSession = null;
            UpdateDisplay();
        }

        private void OpenSerialPort()
        {
            try
            {
                serialPort.Close();

                if ( Config.GetConfig().COMPort == null )
                {
                    Config.GetConfig().COMPort = "COM1";
                }

                serialPort.PortName = Config.GetConfig().COMPort;
                serialPort.BaudRate = 9600;
                serialPort.Parity = Parity.None;
                serialPort.DataBits = 8;
                serialPort.StopBits = StopBits.One;

                serialPort.Open();
            }
            catch ( Exception ex )
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void HRZoneTrainer_Load(object sender, EventArgs e)
        {
            Bounds = m_Bounds;
            OpenSerialPort();
        }

        private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // Buffer and process binary data
            while ( serialPort.BytesToRead > 0 )
            {
                m_Buffer.Add((byte) serialPort.ReadByte());
            }

            int nIndex = m_Buffer.IndexOf(0xD);

            if ( nIndex > -1 )
            {
                for ( int y = 0; y <= nIndex; y++ )
                {
                    m_CurrentReturn.Add(m_Buffer[y]);
                }

                m_Buffer.RemoveRange(0, nIndex + 1);

                ASCIIEncoding ASCII  = new ASCIIEncoding();
                String stringHR = ASCII.GetString(m_CurrentReturn.ToArray());

                string []splitHRString = stringHR.Split (' ');

                if ( splitHRString.Length > 3 )
                {
                    byte statusByte = byte.Parse(splitHRString[0]);
                    m_HRNoData = m_HRReAcquiringSeries = m_HRBadData = false;

                    if ( ( statusByte & 0x2 ) > 0 )
                    {
                        m_HRNoData = true;
                    }

                    if ( ( statusByte & 0x4 ) > 0 )
                    {
                        m_HRReAcquiringSeries = true;
                    }

                    if ( ( statusByte & 0x8 ) > 0 )
                    {
                        m_HRBadData = true;
                    }

                    m_HRLatest = Int32.Parse(splitHRString[2]);
                }

                m_CurrentReturn.Clear();
            }
            else
            {
                foreach ( byte thisByte in m_Buffer )
                {
                    m_CurrentReturn.Add(thisByte);
                }

                m_Buffer.Clear();
            }
        }

        private void HRZoneTrainer_KeyUp(object sender, KeyEventArgs e)
        {
            if ( e.KeyCode == Keys.F11 )
            {
                fullScreenToolStripMenuItem_Click(fullScreenToolStripMenuItem, null);
            }
        }

        private void FullScreen(bool showFullScreen)
        {
            // if the window is in normal mode (sizable) change to full window mode
            if ( showFullScreen )
            {
                // hide the menu bar 
                menuStrip.Hide();

                // disable the window border
                FormBorderStyle = FormBorderStyle.None;

                // safe the current position and size
                m_Bounds = Bounds;

                // resize the window to full screen size and make it top most
                WindowState = FormWindowState.Maximized;
                TopMost = true;
            }
            else // the window is already in full mode switch back to normal mode
            {
                TopMost = false;

                // show the menu bar 
                menuStrip.Show();

                // set the position and size back to the value before full window mode
                Bounds = m_Bounds;

                // enable the window border
                FormBorderStyle = FormBorderStyle.Sizable;

                WindowState = FormWindowState.Normal; 
            }
        }

        private void antiToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if ( sender == antiToolStripMenuItem )
            {
                if ( Config.GetConfig().AntiAliasing )
                {
                    antiToolStripMenuItem.Checked = false;
                    HRGraph.IsAntiAlias = false;
                    Config.GetConfig().AntiAliasing = false;
                }
                else
                {
                    antiToolStripMenuItem.Checked = true;
                    HRGraph.IsAntiAlias = true;
                    Config.GetConfig().AntiAliasing = true;
                }

                HRGraph.Invalidate();
            }
        }

        private void autoSaveSessionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if ( sender == autoSaveSessionToolStripMenuItem )
            {
                if ( Config.GetConfig().AutoSave )
                {
                    autoSaveSessionToolStripMenuItem.Checked = false;
                    Config.GetConfig().AutoSave = false;
                }
                else
                {
                    autoSaveSessionToolStripMenuItem.Checked = true;
                    Config.GetConfig().AutoSave = true;
                }
            }
        }

        private void fullScreenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if ( sender == fullScreenToolStripMenuItem )
            {
                if ( Config.GetConfig().FullScreen )
                {
                    fullScreenToolStripMenuItem.Checked = false;
                    Config.GetConfig().FullScreen = false;
                }
                else
                {
                    fullScreenToolStripMenuItem.Checked = true;
                    Config.GetConfig().FullScreen = true;
                }

                FullScreen(Config.GetConfig().FullScreen);
            }
        }

        private void selectCOMPortToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            SelectSerialPort serialPortSelector = new SelectSerialPort();

            serialPortSelector.SerialPorts = SerialPort.GetPortNames();
            serialPortSelector.DefaultPort = Config.GetConfig().COMPort;

            if ( serialPortSelector.ShowDialog() == DialogResult.OK )
            {
                Config.GetConfig().COMPort = serialPortSelector.SelectedSerialPort;
                OpenSerialPort();
            }
        }

        private void setupZonesToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            HRZone hRZone = new HRZone(Config.GetConfig().HRThreshold,
                                       Config.GetConfig().HRMaximum,
                                       Config.GetConfig().CurrentZoneSelection);

            if ( hRZone.ShowDialog() == DialogResult.OK )
            {
                Config.GetConfig().HRThreshold = hRZone.m_zoneCalculation.HRThreshold;
                Config.GetConfig().HRMaximum = hRZone.m_zoneCalculation.HRMaximum;
                Config.GetConfig().CurrentZoneSelection = hRZone.m_zoneCalculation.CurrentZoneSelection;

                m_zoneCalculation.CurrentZoneSelection = hRZone.m_zoneCalculation.CurrentZoneSelection;
                m_zoneCalculation.HRThreshold = hRZone.m_zoneCalculation.HRThreshold;
                m_zoneCalculation.HRMaximum = hRZone.m_zoneCalculation.HRMaximum;

                CreateChart(HRGraph);
            }
        }

        private void heartRateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Config.GetConfig().GraphType = GraphType.HeartRate;
            SetGraphTypeMenu(Config.GetConfig().GraphType);
            CreateChart(HRGraph);
        }

        private void heartRatePercentageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Config.GetConfig().GraphType = GraphType.HeartRatePercentage;
            SetGraphTypeMenu(Config.GetConfig().GraphType);
            CreateChart(HRGraph);
        }

        ProgramState m_programState = ProgramState.Initialised;

        LineItem m_HRCurve;
        LineItem m_HRCurvePreviousSession;
        BoxObj m_tracerBox;

        Session m_thisSession;
        Session m_previousSession = null;

        int m_HRLatest = 0;

        Rectangle m_Bounds = Config.GetConfig().Bounds;

        public bool m_HRNoData = false;
        public bool m_HRReAcquiringSeries = false;
        public bool m_HRBadData = false;

        private List<byte> m_Buffer = new List<byte>();
        private List<byte> m_CurrentReturn = new List<byte>();

        ZoneCalculation m_zoneCalculation = new ZoneCalculation(Config.GetConfig().HRThreshold, Config.GetConfig().HRMaximum, Config.GetConfig().CurrentZoneSelection);

    }
}
